package com.hskn.hss.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.hskn.hss.entity.LatLngEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Slf4j
@Component
public class LocationUtils {

    private static final double EARTH_RADIUS = 6378.137;
    private String url;
    private String appkey;

    private static double rad(double d) {
        return d * Math.PI / 180.0;
    }

    @Value("${tianditu.url}")
    public void setUrl(String param) {
        url = param;
    }

    @Value("${tianditu.appkey}")
    public void setAppkey(String param) {
        appkey = param;
    }

    /**
     * 通过经纬度获取距离(单位：米)
     *
     * @param lat1
     * @param lng1
     * @param lat2
     * @param lng2
     * @return
     */
    public double getDistance(double lat1, double lng1, double lat2, double lng2) {
        double radLat1 = rad(lat1);
        double radLat2 = rad(lat2);
        double a = radLat1 - radLat2;
        double b = rad(lng1) - rad(lng2);
        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2)
                + Math.cos(radLat1) * Math.cos(radLat2)
                * Math.pow(Math.sin(b / 2), 2)));
        s = s * EARTH_RADIUS;
        s = Math.round(s * 10000d) / 10000d;
        s = s * 1000;
        return s;
    }

    public double getDistance(String lat1, String lng1, String lat2, String lng2) {
        return getDistance(Double.parseDouble(lat1), Double.parseDouble(lng1), Double.parseDouble(lat2), Double.parseDouble(lng2));
    }


    public Double getKmByLatLngList(String latLngJsonList, String returnType) {
        List<LatLngEntity> latLngEntityList = new ArrayList<>();
        JSONArray array = JSONArray.parseArray(latLngJsonList);
        if (array.size() > 0) {
            for (int j = 0; j < array.size(); j++) {
                JSONObject json = JSON.parseObject(array.get(j).toString());
                LatLngEntity latLngEntity = new LatLngEntity();
                latLngEntity.setLat(Double.parseDouble(json.getString("lat")));
                latLngEntity.setLng(Double.parseDouble(json.getString("lng")));
                latLngEntityList.add(latLngEntity);
            }
        }
        return getKmByLatLngList(latLngEntityList, returnType);
    }

    public Double getKmByLatLngList(List<LatLngEntity> latLngJsonList, String returnType) {
        double km = 0D;
        for (int i = 1; i < latLngJsonList.size(); i++) {
            km += getDistance(latLngJsonList.get(i).getLat(), latLngJsonList.get(i).getLng(), latLngJsonList.get(i - 1).getLat(), latLngJsonList.get(i - 1).getLng());
        }
        if (returnType.equals("km")) {
            return km / 1000;
        } else if (returnType.equals("m")) {
            return km;
        } else {
            return 0D;
        }
    }

    public String getAddress(String lng, String lat) {
        Jedis jedis = null;
        String address = null;
        if (StringUtils.isEmpty(lng) || StringUtils.isEmpty(lat)) {
            return address;
        }
        try {
            //从redis获取地址，如果有那么直接返回，如果没有，那么调用天地图API接口，然后保存redis
            jedis = JedisPoolUtils.getJedis();
            String key = getKey(lng, lat);
            address = jedis.get(key);
            if (!StringUtils.isEmpty(address)) {
                return address;
            }
            //根据坐标获取位置名称
            String str = MyHttpUtils.sendGet(url, "postStr={'lon':" + lng + ",'lat':" + lat + ",'ver':1}&type=geocode&tk=" + appkey);
            JSONObject json = JSON.parseObject(str);
            if (null == json) {
                log.error("==调用天地图API接口失败（可能达到请求次数上限），返回结果：{}", str);
                return address;
            }
            String status = json.get("status").toString();
            if ("0".equals(status)) {
                JSONObject result = JSON.parseObject(json.get("result").toString());
                address = result.get("formatted_address").toString();
                jedis.set(key, address);
            } else {
                log.error("--调用天地图API接口失败");
                address = null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(), e);
            log.error("==调用天地图API接口失败，lng:{},lat:{}", lng, lat);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return address;
    }

    public String getKey(String lng, String lat) {
        Double lngD = Double.parseDouble(lng);
        Double latD = Double.parseDouble(lat);
        DecimalFormat df = new DecimalFormat("#.0000");
        String result = df.format(lngD) + "," + df.format(latD);
        return result;
    }

    //判断两点是否相同
    public boolean checkTwoPointSame(double lng, double lat, double nextLng, double nextLat) {
        double seuil = 0.00000001;
        return lng * lng + lat * lat - nextLat * nextLat - nextLng * nextLng < seuil;
    }

    public boolean checkTwoPointSame(String lng, String lat, String nextLng, String nextLat) {
        return checkTwoPointSame(Double.parseDouble(lng), Double.parseDouble(lat), Double.parseDouble(nextLng), Double.parseDouble(nextLat));
    }

    //判断两点经纬度是否相同
    public boolean checkTwoPointSameComplete(double lng, double lat, double nextLng, double nextLat) {
        return lng == nextLng && lat == nextLat;
    }

    /**
     * ture为动
     *
     * @param differenceMeter
     * @param timeDifference
     * @return
     */
    public boolean realMove(double differenceMeter, Long timeDifference) {
        //两个定位数据，距离小于20米，且时间间隔大于10分钟，认为没有移动【解决车辆停止一段时间后，再启动电源，然后立马关闭电源的情况】
        return timeDifference <= 10 * 60 * 1000 || !(differenceMeter < 20);
    }

    /**
     * 判断车辆离线 ture为离线
     *
     * @param differenceMeter
     * @param timeDifference
     * @return
     */
    public boolean realOffLine(Double differenceMeter, Long timeDifference) {
        if (Objects.nonNull(differenceMeter) && Objects.nonNull(timeDifference)) {
            return timeDifference > 2 * 60 * 1000 && differenceMeter <= 20;
        }
        return false;
    }
}
